`ifndef ROUND_ROBIN_ARBITER_SV
`define ROUND_ROBIN_ARBITER_SV

module round_robin_arbiter (
	input              clk,
	input              rst_n,
	input        [3:0] req,
	output logic [3:0] grant);

	logic [1:0] rotate_ptr;
	logic [3:0] shift_req;
	logic [3:0] shift_grant;
	logic [3:0] next_grant;
	
	// 按当前循环优先级移位req
	always_comb begin
		case (rotate_ptr)
			2'h0: shift_req = req;
			2'h1: shift_req = {req[0]  , req[3:1]};
			2'h2: shift_req = {req[1:0], req[3:2]};
			2'h3: shift_req = {req[2:0], req[3]};
		endcase
	end
	
	// 优先级仲裁器
	always_comb begin
		shift_grant = 4'h0;
		if      (shift_req[0]) shift_grant[0] = 1'h1;
		else if (shift_req[1]) shift_grant[1] = 1'h1;
		else if (shift_req[2]) shift_grant[2] = 1'h1;
		else if (shift_req[3]) shift_grant[3] = 1'h1;
	end
	
	// 生成新的grant
	always_comb begin
		case (rotate_ptr)
			2'h0: next_grant = shift_grant;
			2'h1: next_grant = {shift_grant[2:0], shift_grant[3]};
			2'h2: next_grant = {shift_grant[1:0], shift_grant[3:2]};
			2'h3: next_grant = {shift_grant[0]  , shift_grant[3:1]};
		endcase
	end
	
	// 更新grant
	always_ff @(posedge clk or negedge rst_n) begin
		if (!rst_n) grant <= 4'h0;
		else        grant <= next_grant & ~grant;
	end
	
	// 更新循环指针
	always_ff @(posedge clk or negedge rst_n) begin
		if (!rst_n) rotate_ptr <= 2'h0;
		else begin
			case (grant)
				grant[0]: rotate_ptr <= 2'h1;
				grant[1]: rotate_ptr <= 2'h2;
				grant[2]: rotate_ptr <= 2'h3;
				grant[3]: rotate_ptr <= 2'h0;
			endcase
		end
	end
endmodule

`endif
